#include "stdafx.h"
#include "Display.h"
#include "VertexCollection.h"
#include "Mesh.h"
extern Display *gDisplay;

DWORD F2DWORD(float f);

struct RenderTread
{
	RenderTread(int id) : mID(id) { }
	void operator()()
	{
		gDisplay->Render();
	}
	int mID;
};

Display::Display(HWND window, 
			IDirect3DDevice9* device, 
			IDirect3D9* d3d):
	mWindow(window), mDevice(device), mD3D(d3d)
{
	mWidth = 800;
	mHeight = 600;
	if(!d3d || !device) 
		CreateDevice();	
	InitD3DRenderState();
	TestMeshLoad();
}
void Display::TestMeshLoad()
{
	Mesh m;
	Mesh::LoadFromFile("data\\quad.mw", m);
	m.UpdateColorBufferFromVertices(mDevice);
	m.UpdateVertexBufferFromVertices(mDevice);
	LPDIRECT3DVERTEXDECLARATION9 vertexDeclaration;
	mDevice->CreateVertexDeclaration( KVertexCollectionDeclaration, &vertexDeclaration );
	mDevice->SetVertexDeclaration( vertexDeclaration );
	mDevice->SetStreamSource( 0, m.GetVertexBuffer(), 0, sizeof(Vertex) );
	mDevice->SetStreamSource( 1, m.GetColorBuffer(),0, sizeof(Color));
}
void Display::Render()
{
	mDevice->Clear(0,0,D3DCLEAR_TARGET, D3DCOLOR_XRGB(30, 20, 80), 1.0f, 0);
	mDevice->BeginScene();
		mDevice->DrawPrimitive(D3DPT_TRIANGLELIST,0,2);
	mDevice->EndScene();
	mDevice->Present(NULL, NULL, NULL, NULL);
	Sleep(10);
}

HRESULT Display::InitD3DRenderState()
{
	/// View matrix
	// Initialise our vectors
	D3DXVECTOR3 vEyePt(0.0f, 0.0f, 10.0f);
	D3DXVECTOR3 vLookatPt(0.0f, 0.0f, 0.0f);
	D3DXVECTOR3 vUpVec(0.0f, 1.0f, 0.0f);
	D3DXMATRIX matView;
	D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );
	mDevice->SetTransform( D3DTS_VIEW, &matView ); 

	/// Projection matrix
	D3DXMATRIX matProj;
	float fAspect = ((float)mWidth)/mHeight;
	D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, fAspect, 0.1f, 1000.0f );
	mDevice->SetTransform( D3DTS_PROJECTION, &matProj );

	/// World matrix
	D3DXMATRIX matWorld;
	D3DXMatrixIdentity(&matWorld);
	mDevice->SetTransform( D3DTS_WORLD, &matWorld );
	
	mDevice->SetRenderState(D3DRS_LIGHTING, FALSE);

	SetPointSize(0.05f);
	EnableBlend();

	
	return S_OK;
}

void Display::SetPointSize(float s, float m){
	mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);
	mDevice->SetRenderState(D3DRS_POINTSCALEENABLE, TRUE);
	mDevice->SetRenderState(D3DRS_POINTSIZE, F2DWORD(s));
	mDevice->SetRenderState(D3DRS_POINTSIZE_MIN, F2DWORD(0.001f));
}

void Display::EnableBlend(){
	mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,true);
	mDevice->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA);
	mDevice->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA);
	mDevice->SetRenderState(D3DRS_BLENDOP,D3DBLENDOP_ADD);
}

HRESULT Display::CreateDevice()
{
	if(!mD3D)
		mD3D.Attach(Direct3DCreate9(D3D_SDK_VERSION));

	HRESULT hr;
	mDevice = NULL;
	D3DDISPLAYMODE dm;

	hr = mD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &dm);
	D3DPRESENT_PARAMETERS pp;
	ZeroMemory(&pp, sizeof(pp));
	pp.Windowed = TRUE;
	pp.hDeviceWindow = mWindow;
	pp.SwapEffect = D3DSWAPEFFECT_DISCARD;
	pp.BackBufferFormat = dm.Format;
	
	FAIL_RET( mD3D->CreateDevice(  D3DADAPTER_DEFAULT,
								D3DDEVTYPE_HAL,
								mWindow,
								D3DCREATE_HARDWARE_VERTEXPROCESSING |
								D3DCREATE_MULTITHREADED,
								&pp,
								&mDevice));		
	return hr;
}
